#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, platform
import SCons
import SCons.Script
import logging
import fnmatch
import shutil

from build import util, mixxx, depends

print('SConscript.env cwd: ' + os.getcwd())
Import('build')

# Grab the created environment from the MixxxBuild
env = build.env

# We are in the variant_dir (win|mac|lin)XX_build, and the 'src' subdirectory
# may not exist yet.
try:
    os.mkdir('src')
except:
    pass

# TODO(rryan): This logic should be written in a more SCons-friendly way, since
# it depends on the cwd being the variant_dir to work properly.
if os.path.exists('../build.h'):
    # If a build.h exists in the project root mixxx/ directory then use that
    # instead of writing our own. This is mostly since when we build Debian
    # packages we don't have any of the Git metadata so we can't write one
    # ourselves.
    shutil.copy('../build.h', 'src/build.h')
else:
    util.write_build_header('src/build.h')

conf = Configure(env, custom_tests = { 'CheckForPKGConfig' : util.CheckForPKGConfig,
                                       'CheckForPKG' : util.CheckForPKG })

if not conf.CheckCXX():
    print("Building with CXX: %s" % env['CXX'])
    print("A compiler with C++11 support is required.")
    Exit(1)

available_features = [depends.MixxxCore]
extra_features = build.get_features()
available_features.extend(extra_features)

# Instantiate the features
available_features = [feature_class() for feature_class in available_features]

visited_dependencies = set()
active_dependencies = []
unmet_dependencies = False
# Don't configure if the user is askign for help or a clean.
should_configure = not GetOption('help') and not GetOption('clean')
if not should_configure:
    print('Skipping dependency configuration.')

def visit_dependency(dependency_class, build, conf):
    """Recursively configure all dependencies.

    Skip over dependencies we have already setup.
    """
    global unmet_dependencies

    if dependency_class in visited_dependencies:
        return
    visited_dependencies.add(dependency_class)
    dependency = dependency_class()

    try:
        if should_configure:
            print("Configuring %s" % dependency.name)
            dependency.configure(build, conf)
    except Exception as e:
        logging.error("Unmet dependency: %s" % e)
        unmet_dependencies = True
    active_dependencies.append(dependency)

    for sub_dependency in dependency.depends(build):
        visit_dependency(sub_dependency, build, conf)

for feature in available_features:
    try:
        if should_configure:
            print("Configuring %s" % feature.name)
            feature.configure(build, conf)

        # Only process the feature's dependencies if it's enabled
        if feature.enabled(build):
            active_dependencies.append(feature)
            for dependency in feature.depends(build):
                visit_dependency(dependency, build, conf)
    except Exception as e:
        logging.error("Unmet dependency: %s" % e)
        unmet_dependencies = True

if unmet_dependencies:
    logging.error("Build had unmet dependencies. Exiting.")
    Exit(1)

sources = []

# Query each active dependency for sources they require
for dependency in active_dependencies:
    dep_sources = dependency.sources(build)
    if dep_sources is not None:
        sources.extend(dep_sources)
    # If there's additional env variables that need to be set after the
    # configure checks have run, then we'll take care of that now.
    dependency.post_dependency_check_configure(build, conf)

env = conf.Finish()

#Tell SCons to build libraries that are bundled with Mixxx
#===================================================

print("Features Summary:")
print("================")

for feature in available_features:
    message = "Enabled" if feature.enabled(build) else "Disabled"

    # If the plugin has a status message, show it instead
    if len(feature.status) > 0:
        message = "%s" % feature.status

    print("%035s... %s" % (feature.description(), message))

build_flags = ' '.join(sorted(
    [('%s=%s' % (k,v) if v is not None else k) for k,v in build.flags.items() if v is not None]))

### Put flags info into a file
with open("src/build.h", "a") as f:
    f.write('#define BUILD_FLAGS "' + build_flags + '"\n')

# Print the build flags. This is useful if the flags have been cached,
# ie. if you just run "scons" and want to see the flags that you used last time.
print("================")
print("Building with flags: %s" % build_flags)
print("Building with CC: %s" % env['CC'])
print("Building with CXX: %s" % env['CXX'])
print("Building with CCFLAGS: %s" % env['CCFLAGS'])
print("Building with CPPDEFINES: %s" % ' '.join(['-D'+'='.join(pair) if not isinstance(pair, str) else '-D'+pair for pair in env['CPPDEFINES']]))
print("Building with CXXFLAGS: %s" % env['CXXFLAGS'])
print("Building with LINKFLAGS: %s" % env['LINKFLAGS'])
print("Building with LIBS: %s" % ' '.join(env['LIBS']))
print("Building with PATH: %s" % env['ENV']['PATH'])
if build.platform_is_windows:
    print("Building with INCLUDE: %s" % env['ENV']['INCLUDE'])
    print("Building with LIB: %s" % env['ENV']['LIB'])
    print("Building with LIBPATH: %s" % env['ENV']['LIBPATH'])
print("================")

Export('sources')
